package com.llb.llbliving.commodity.service.impl;

import com.llb.llbliving.commodity.vo.Catalog2Vo;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.llb.common.utils.PageUtils;
import com.llb.common.utils.Query;

import com.llb.llbliving.commodity.dao.CategoryDao;
import com.llb.llbliving.commodity.entity.CategoryEntity;
import com.llb.llbliving.commodity.service.CategoryService;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {
    //这里会涉及到java8的流式计算+递归操作


    @Override
    public List<CategoryEntity> listTree() {
        //1.查出所有的分类数据
        List<CategoryEntity> entities = baseMapper.selectList(null);
        //2.组装成层级树形结构
        //2.1 过滤，返回一级分类
        //2.2 进行map映射操作，给每个分类设置对应的子分类
        //2.3 进行排序sorted操作
        //2.4 将处理好的数据收集/转换到集合

        List<CategoryEntity> categoryTree = entities.stream().filter(categoryEntity -> {
            //2.1 过滤，返回一级分类
            return categoryEntity.getParentId() == 0;
        }).map(category -> {
            //2.2 进行map映射操作，给每个一级分类设置对应的子分类
            category.setChildrenCategories(getChildrenCategories(category, entities));
            return category;
        }).sorted((category1, category2) -> {
            //2.3 进行排序sorted操作,按照sort升序排列
            return (category1.getSort() == null ? 0 : category1.getSort())
                    - (category2.getSort() == null ? 0 : category2.getSort());
        }).collect(Collectors.toList());

        //3.返回带有层级关系数据
        return categoryTree;
    }

    //递归查询所有分类的子分类
    private List<CategoryEntity> getChildrenCategories(CategoryEntity root, List<CategoryEntity> all) {
        List<CategoryEntity> collect = all.stream().filter(categoryEntity -> {
            //这里有个bug，如果直接categoryEntity.getParentId()==root.getId(),得到的是Long包装类
            //public static Long valueOf(long l) {
            //        final int offset = 128;
            //        if (l >= -128 && l <= 127) { // will cache
            //            return LongCache.cache[(int)l + offset];
            //        }
            //        return new Long(l);
            //    }
            //看源码可知当l >= -128 && l <= 127,返回的是同一个对象,==判断的时候是true，
            // 可是如果超出了这个范围，就会new一个新对象，这就会导致虽然值相同，可是==判断的时候是false
            //可以用longvalue，也可以用equals
            return categoryEntity.getParentId().longValue() == root.getId().longValue();
        }).map(category -> {
            //找到子分类，并设置，然后递归
            category.setChildrenCategories(getChildrenCategories(category, all));
            return category;
        }).sorted((cate1, cate2) -> {
            return (cate1.getSort() == null ? 0 : cate1.getSort()) - (cate2.getSort() == null ? 0 : cate2.getSort());
        }).collect(Collectors.toList());
        return collect;
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public Long[] getCascadedCategoryId(Long categoryId) {
        List<Long> cascadedCategoryId = new ArrayList<>();
        getParentCategoryId(categoryId, cascadedCategoryId);
        //将顺序翻转
        Collections.reverse(cascadedCategoryId);
        return cascadedCategoryId.toArray(new Long[cascadedCategoryId.size()]);
    }

    @Override
    public List<CategoryEntity> getLevel1Categories() {
        QueryWrapper<CategoryEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id",0);
        this.baseMapper.selectList(queryWrapper);
        return this.baseMapper.getLevel1Categories();
    }

    @Override
    public Map<String, List<Catalog2Vo>> getCatalogJson() {
        //获取2级分类的集合
        List<CategoryEntity> categoryEntities=this.listTree();

        Map<String, List<Catalog2Vo>> catalog2vlist  =categoryEntities.stream().collect(Collectors.toMap(
                k->{
                   return k.getId().toString();
                },
                v->{
                    //List<Catalog2Vo> catalog2Vos=new ArrayList<>();
                    List<CategoryEntity> childrenCategories = v.getChildrenCategories();
                    List<Catalog2Vo> catalog2Vos=childrenCategories.stream().map(s->{
                        Catalog2Vo catalog2Vo = new Catalog2Vo();
                        catalog2Vo.setCatalog1Id(v.getId().toString());
                        catalog2Vo.setName(s.getName());
                        catalog2Vo.setId(s.getId().toString());
                        List<Catalog2Vo.Category3Vo> catalog3List=
                                s.getChildrenCategories().stream().
                                        map(q->{
                                            Catalog2Vo.Category3Vo category3Vo = new Catalog2Vo.Category3Vo();
                                            category3Vo.setCatalog2Id(s.getId().toString());
                                            category3Vo.setId(q.getId().toString());
                                            category3Vo.setName(q.getName());
                                            return category3Vo;
                                        }).
                                        collect(Collectors.toList());
                        catalog2Vo.setCatalog3List(catalog3List);
                        return catalog2Vo;
                    }).collect(Collectors.toList());
                    return catalog2Vos;
                }
        ));
        return catalog2vlist;

    }

    /**
     * 该方法递归的找到 categoryId 的所有父分类 id , 并存放到 categories* 注意得到的所有分类 id 是一个逆序的
     * @param categoryId
     * @param categories
     * @return
     */
    private List<Long> getParentCategoryId(Long categoryId,List<Long> categories){//1、将当前分类 id 放入 categories 数组
        categories.add(categoryId);
        CategoryEntity categoryEntity = this.getById(categoryId);
        if(categoryEntity.getParentId() !=0){
            getParentCategoryId(categoryEntity.getParentId(),categories);
        }
        return categories;
    }

}